# --------------------------------------------------------------------

cdef extern from "mpi.h":

    MPI_Comm MPI_COMM_NULL
    MPI_Comm MPI_COMM_SELF
    MPI_Comm MPI_COMM_WORLD

cdef extern from "petsc.h":
    MPI_Comm PETSC_COMM_NULL "MPI_COMM_NULL"
    MPI_Comm PETSC_COMM_SELF
    MPI_Comm PETSC_COMM_WORLD

from petsc4py.PETSc cimport GetComm
from petsc4py.PETSc cimport GetCommDefault
cdef inline MPI_Comm def_Comm(object comm, MPI_Comm defv) except *:
     return GetComm(comm, defv)

# --------------------------------------------------------------------

cdef extern from * nogil:
    int PetscObjectReference(PetscObject)
    int PetscObjectDestroy(PetscObject*)
    int PetscObjectCompose(PetscObject,char[],PetscObject)

cdef inline int PetscINCREF(PetscObject *obj):
    if obj    == NULL: return 0
    if obj[0] == NULL: return 0
    return PetscObjectReference(obj[0])

cdef inline int PetscCLEAR(PetscObject* obj):
    if obj    == NULL: return 0
    if obj[0] == NULL: return 0
    cdef PetscObject tmp
    tmp = obj[0]; obj[0] = NULL
    return PetscObjectDestroy(&tmp)

# --------------------------------------------------------------------

cdef extern from "petsc.h":
    enum: PETSC_DEFAULT

cdef extern from "petscvec.h":
    int VecSet(PetscVec,PetscScalar)
    int VecCopy(PetscVec,PetscVec)

cdef extern from "petscmat.h":
    ctypedef enum  PetscMatStructure "MatStructure":
        MAT_SAME_NONZERO_PATTERN      "SAME_NONZERO_PATTERN"
        MAT_DIFFERENT_NONZERO_PATTERN "DIFFERENT_NONZERO_PATTERN"
        MAT_SUBSET_NONZERO_PATTERN    "SUBSET_NONZERO_PATTERN"
        MAT_SAME_PRECONDITIONER       "SAME_PRECONDITIONER"

cdef inline PetscMatStructure matstructure(object structure) except <PetscMatStructure>(-1):
    if   structure is None:  return MAT_DIFFERENT_NONZERO_PATTERN
    elif structure is False: return MAT_DIFFERENT_NONZERO_PATTERN
    elif structure is True:  return MAT_SAME_NONZERO_PATTERN
    else:                    return structure

# --------------------------------------------------------------------

cdef inline Vec new_Vec(PetscVec vec):
    cdef Vec ob = <Vec> Vec()
    ob.vec = vec
    PetscINCREF(ob.obj)
    return ob

cdef inline Mat new_Mat(PetscMat mat):
    cdef Mat ob = <Mat> Mat()
    ob.mat = mat
    PetscINCREF(ob.obj)
    return ob

cdef inline KSP new_KSP(PetscKSP ksp):
    cdef KSP ob = <KSP> KSP()
    ob.ksp = ksp
    PetscINCREF(ob.obj)
    return ob

# --------------------------------------------------------------------
